package cc.minos.game.go.board
{
	import cc.minos.utils.ArrayUtil;
	import flash.geom.Point;
	
	/**
	 * ...
	 * 围棋
	 * @author Minos
	 */
	public class GoBoard extends Board
	{
		//最后一步杀死的棋子数
		public var lastKillCount:int;
		//下一手的禁着点（打劫的情况，   不能连续提，   必须寻劫材)
		protected var forbidMove:Point;
		
		public function GoBoard( chess:Array = null )
		{
			super( chess );
		}
		
		override protected function init():void
		{
			super.init();
			offsets = [[ -1 , 0 ] , [ 1 , 0 ] , [ 0 , -1 ] , [ 0 , 1 ] ];
			lastKillCount = 0;
			forbidMove = new Point( -1 , -1 );
		}
		
		public function IsValidMove( color:int , row:int , col:int ):Boolean
		{
			if ( chess[ row ][ col ] != EMPTY )
				return false;
			else if ( row == forbidMove.x && col == forbidMove.y )
				return false;
			else
			{
				chess[ row ][ col ] = color;
				var chuanSelf:Array = findChuan( row , col );
				if ( countChuanGas( chuanSelf ) > 0 )
				{
					chess[ row ][ col ] = EMPTY;
					return true;
				}
				else
				{
					chess[ row ][ col ] = EMPTY;
					var deads:Array = findEnemiesCanKill( color , row , col );
					if ( deads.length > 0 )
						return true;
					else
						return false;
				}
			}
		}
		
		/**
		 * 走一步&提去死子&更新统计数据
		 * @param	color
		 * @param	row
		 * @param	col
		 */
		override public function makeMove( color:int , row:int , col:int ):void
		{
			//得到死子集合
			var deads:Array = findEnemiesCanKill( color , row , col );
			// 判断是否劫，   如果是，   则设定下一步的禁手，   使得对方不能立刻回提
			var isJie:Boolean = false;
			var p:Point = new Point();
			if ( deads.length == 1 )
			{
				p = deads[ 0 ]
				//try
				chess[ row ][ col ] = color;
				chess[ p.x ][ p.y ] = EMPTY;
				var d:Array = findEnemiesCanKill( -color , p.x , p.y );
				if ( d.length == 1 )
				{
					if ( d[ 0 ].x == row && d[ 0 ].y == col )
						isJie = true;
				}
				
				chess[ row ][ col ] = EMPTY;
				chess[ p.x ][ p.y ] = -color;
			}
			if ( isJie )
				forbidMove = p;
			else
				forbidMove = new Point( -1 , -1 );
			//落子
			chess[ row ][ col ] = color;
			//提子
			for ( var i:int = 0 ; i < deads.length ; i++ )
			{
				p = deads[ i ];
				chess[ p.x ][ p.y ] = EMPTY;
			}
			if ( deads.length > 0 )
			{
				removeDeads( deads );
			}
			lastKillCount = deads.length;
			lastMove = new Point( row , col );
		}
		
		protected function removeDeads( deads:Array ):void
		{
		}
		
		override public function findEnemiesCanKill( color:int , row:int , col:int ):Array
		{
			if ( chess[ row ][ col ] != EMPTY )
				return null;
			chess[ row ][ col ] = color;
			
			var deads:Array = [];
			var visiteds:Array = [];
			//开始判断能够提取的敌方死子 
			var xpos:int , ypos:int;
			
			for ( var i:int = 0 , len:int = offsets.length ; i < len ; i++ )
			{
				xpos = row + offsets[ i ][ 0 ];
				ypos = col + offsets[ i ][ 1 ];
				if ( xpos >= 0 && xpos < cols && ypos >= 0 && ypos < rows )
				{
					if ( chess[ xpos ][ ypos ] == -color )
					{
						//如果目前位置已经在前面某个方向的探索过程中找到，   则不用判断了。 
						//因为不同方向的棋子可能是属于同一个串的
						if ( !isExit( visiteds , xpos , ypos ) )
						{
							//寻找包含该位置的串 
							var chuan:Array = findChuan( xpos , ypos );
							//算串的气
							var chuanGas:int = countChuanGas( chuan );
							//加到已访问的列表
							//visiteds.push( chuan );
							ArrayUtil.merge( visiteds , chuan );
							if ( chuanGas == 0 )
							{
								ArrayUtil.merge( deads , chuan );
							}
						}
					}
				}
			}
			visiteds = [];
			//恢复试落的位置原先的状态
			chess[ row ][ col ] = EMPTY;
			return deads;
		}
		
		//判断一个位置是否探索过
		protected function isExitB( array:Array , col:int , row:int ):Boolean
		{
			if ( array.length == 0 )
				return false;
			var result:Boolean = false;
			for ( var j:int = 0 ; j < array.length ; j++ )
			{
				if ( array[ j ][ 0 ] == col && array[ j ][ 1 ] == row )
				{
					result = true;
					break;
				}
			}
			return result;
		}
		
		//算串的气
		protected function countChuanGas( chuan:Array ):int
		{
			if ( chuan.length == 0 )
				return 0;
			var gas:int = 0;
			for ( var i:int = 0 ; i < chuan.length ; i++ )
			{
				gas += countGas( chuan[ i ].x , chuan[ i ].y );
			}
			return gas;
		}
		
		//算气
		protected function countGas( row:int , col:int ):int
		{
			var gas:int = 0;
			var xpos:int , ypos:int;
			for ( var i:int = 0 , len:int = offsets.length ; i < len ; i++ )
			{
				xpos = row + offsets[ i ][ 0 ];
				ypos = col + offsets[ i ][ 1 ];
				if ( xpos >= 0 && xpos < cols && ypos >= 0 && ypos < rows )
				{
					if ( chess[ xpos ][ ypos ] == EMPTY )
						gas++;
				}
			}
			return gas;
		}
		
		//
		protected function isExit( visitedArray:Array , row:int , col:int ):Boolean
		{
			if ( visitedArray.length == 0 )
				return false;
			var result:Boolean = false;
			for ( var i:int = 0 ; i < visitedArray.length ; i++ )
			{
				if ( visitedArray[ i ].x == row && visitedArray[ i ].y == col )
				{
					result = true;
					break;
				}
			}
			return result;
		}
		
		//寻找包含该位置的棋子串
		protected function findChuan( row:int , col:int ):Array
		{
			var chuan:Array = new Array();
			var color:int = chess[ row ][ col ]; //当前的颜色    
			//   加入当前点 
			chuan.push( new Point( row , col ) );
			//   定义两个游标 
			var begin:int = 0;
			var end:int = 0;
			var findCount:int; //发现的邻居数目,   用于循环结束的判断条件 
			do
			{
				findCount = 0;
				//begin   到   end   之间的一些点表示没有探索过四周的那些点
				for ( var i:int = begin ; i <= end ; i++ )
				{
					//对左右上下四个方向进行探索 
					for ( var j:int = 0 ; j < 4 ; j++ )
					{
						var newx:int = chuan[ i ].x + offsets[ j ][ 0 ];
						var newy:int = chuan[ i ].y + offsets[ j ][ 1 ];
						//trace("FindChuan",newx, newy,color);
						//trace("FindChuan",begin, end);
						// 如果该点在棋盘内，且颜色相同，且现有的串中没有，则加入串 
						if ( newx >= 0 && newx < cols && newy >= 0 && newy < rows && chess[ newx ][ newy ] == color && !isExit( chuan , newx , newy ) )
						{
							//trace(newx, newy);
							chuan.push( new Point( newx , newy ) );
							//   寻找到的邻居计数器加   1 
							findCount += 1;
						}
					}
				}
				//   设定下一个循环要列举的开始和结束游标 
				begin = end + 1;
				end = end + findCount;
			} while ( findCount > 0 );
			//如果本轮搜索的所有点都没有邻居了，   也就表示串搜索结束了，   跳出循环 
			//trace("FindChuan",chuan.length);
			return chuan;
		}
	}

}